﻿ 
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using static UnityEditor.Progress;

namespace XFGameFramework.ScriptableObjectSystem
{

    public class ICONGUIContent : GUIContent
    {

        public ICONGUIContent() { }

        public ICONGUIContent(GUIContent content):base(content) { }


        public string projectName;
        public string iconName;
    }

    public class ConfigsWindow : SplitWindow
    {

        [MenuItem("Window/XFKT/XFGameFramework/InstalledExtension/ScriptableObjectConfigs", false, 10)]
        static void Open()
        { 
            CreateWindow<ConfigsWindow>().Show();
        }

        #region 字段

        private const string SELECT_GUID_KEY = "XFGameFramework.ScriptableObjectSystem.SELECT_GUID_KEY";

        //internal List<ScriptableObjectConfigs> allConfigs = new List<ScriptableObjectConfigs>();
         

        private GUIContent currentConfigContent;

        private string searchStr;
         
        [SerializeField]
        private TreeViewStateGroup treeViewStateGroup = new TreeViewStateGroup();

#if UNITY_6000_2_OR_NEWER
        private TreeViewState<int> treeViewState => treeViewStateGroup.Get(currrentScriptableConfigs.GetHashCode());
#else
        private TreeViewState treeViewState => treeViewStateGroup.Get(currrentScriptableConfigs.GetHashCode());
#endif


        public ScriptableObjectListTree scriptableObjectListTree;
          
        internal ScriptableObjectConfigs current;

        internal Vector2 rightScrollPosition; 

        private int currentID;
        public int idChangeCount;
        
        private float lastRepaintCount;

#endregion


        #region 属性

        internal static string SelectGUID
        {
            get
            {
                return EditorPrefs.GetString(SELECT_GUID_KEY,string.Empty);
            }
            set
            {
                EditorPrefs.SetString(SELECT_GUID_KEY, value);
            }

        } 

        internal string CurrentKey
        {
            get {
                string key = string.Format("{0}-{1}", SELECT_GUID_KEY, GetInstanceID());
                return key;
            } 
        }

        internal string ThisSelectGUID
        {
            get
            { 
                return EditorPrefs.GetString(CurrentKey, string.Empty);
            }
            set
            { 
                EditorPrefs.SetString(CurrentKey, value); 
            }

        }

        internal ScriptableObjectConfigs currrentScriptableConfigs;

        private float timer;

        #endregion
         

        #region 生命周期

        private void Awake()
        {
            titleContent = new GUIContent("配置窗口", "配置窗口"); 
        }

         
        private void OnDisable()
        {
             
            // 保存当前窗口选择的文件的guid
            SelectGUID = ThisSelectGUID; 
            // 删除该窗口的key
            EditorPrefs.DeleteKey(CurrentKey); 
        }

        protected override void OnGUI()
        {
            if (Time.realtimeSinceStartup - timer > 1 && currrentScriptableConfigs == null)
            {
                currrentScriptableConfigs = GetCurrentConfig();
                timer = Time.realtimeSinceStartup;
            }

            if (currrentScriptableConfigs == null)
            {
                EmptyGUI();
            }
            else
            {
                base.OnGUI();
            } 
           
        }


        private void Update()
        {
            lastRepaintCount++;
            if (lastRepaintCount > 15)
            { 
                Repaint();
                lastRepaintCount = 0;
            }   
        }

        #endregion


        #region 方法 
         
        private void EmptyGUI()
        {

            GUILayout.BeginHorizontal();

            GUILayout.FlexibleSpace();

            GUILayout.BeginVertical();
            GUILayout.FlexibleSpace();
            GUILayout.Label("未查询到配置文件!");
            if (GUILayout.Button("立即创建"))
            {
                CreateNew();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

        }

        protected override void DrawGUILeft(Rect rect)
        {
            base.DrawGUILeft(rect);
            GUILayout.BeginArea(rect);
            DrawLeft(rect);
            GUILayout.EndArea();
        }

        protected override void DrawGUIRight(Rect rect)
        {
            base.DrawGUIRight(rect);
            GUILayout.BeginArea(rect);
            DrawRight();
            GUILayout.EndArea();
        }

        private void DrawLeft(Rect left)
        { 
            if (currentConfigContent == null)
                currentConfigContent = new GUIContent();

            if (currrentScriptableConfigs == null)
                return;

            currentConfigContent.text = GetDisplayName(currrentScriptableConfigs);
            currentConfigContent.tooltip = AssetDatabase.GetAssetPath(currrentScriptableConfigs);
              
            left.Set(left.x, left.y + 20, left.width , left.height - 20);

            GUI.Box(left, string.Empty, "GroupBox");
  
            if (scriptableObjectListTree != null && scriptableObjectListTree.ScriptableObjectConfigs != currrentScriptableConfigs)
                scriptableObjectListTree = null;

            if (scriptableObjectListTree == null) 
            { 
                scriptableObjectListTree = new ScriptableObjectListTree(currrentScriptableConfigs, currrentScriptableConfigs.configs, treeViewState); 

                scriptableObjectListTree.Reload();
            }
             
            scriptableObjectListTree.OnGUI(left);

           
            GUILayout.BeginHorizontal();
            // 

            EditorGUI.BeginChangeCheck();

            searchStr = EditorGUILayout.TextField(string.Empty, searchStr, "SearchTextField", GUILayout.MinWidth(0));
             
            if (EditorGUI.EndChangeCheck())
            {
                if (string.IsNullOrEmpty(searchStr) && scriptableObjectListTree.state.selectedIDs.Count > 0)
                {
                    EditorApplication.delayCall += () =>
                    {
                        scriptableObjectListTree.FrameItem(scriptableObjectListTree.state.selectedIDs[0]);
                    };
                }
            }

            scriptableObjectListTree.searchString = searchStr;

            if (EditorGUILayout.DropdownButton(currentConfigContent, FocusType.Passive, EditorStyles.toolbarDropDown, GUILayout.MinWidth(0)))
            {
                GenericMenu menu = new GenericMenu();
                List<ScriptableObjectConfigs> configs = ScriptableObjectConfigsController.GetAllConfigs();
                foreach (var item in configs)
                {
                    string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(item));
                    bool isOn = SelectGUID == guid;

                    menu.AddItem(new GUIContent(item.name), isOn, () =>
                    {
                        SelectGUID = guid; 

                        EditorApplication.delayCall += () =>
                        {
                            EditorGUIUtility.PingObject(item);
                        };
                        if (!isOn)
                        {
                            SetCurrentConfigs(item);
                        }
                    });
                }


                menu.AddSeparator(string.Empty);

                menu.AddItem(new GUIContent("新建配表"), false, () =>
                {
                    CreateNew();
                });

                menu.ShowAsContext();
            }

            GUILayout.EndHorizontal();

        }

        private void DrawRight()
        { 
            if (treeViewState.selectedIDs.Count == 1)
            {
                DrawData();
            }
            else if (treeViewState.selectedIDs.Count == 0)
            {
                GUILayout.FlexibleSpace();
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label("空!");
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.FlexibleSpace();
            }
            else
            {
                GUILayout.FlexibleSpace();
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                Color origin = GUI.color;
                GUI.color = Color.yellow;
                GUILayout.Label("不支持同时编辑多个配置!");
                GUI.color = origin;
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.FlexibleSpace();
            } 
        }

        private void DrawData()
        {
            int id = treeViewState.selectedIDs[0];

            if (currentID != id)
            {
                idChangeCount++;
                if (idChangeCount > 1)
                {
                    // 保证当前被return的 不是layout 
                    // 如果layout 被return，直接repaint 就会报错，因为没有计算位置
                    if (Event.current.type != EventType.Layout)
                    {
                        currentID = id;
                        idChangeCount = 0;
                    }
                }
                // 这样处理的目的是 为了防止 EditorGUILayout.DelayedIntField 在编辑时 ,
                // 直接切换id,  EditorGUILayout.DelayedIntField  返回的值会直接给新选中的数据， 导致数据错误的情况
                return;
            }

            ScriptableObjectData data = currrentScriptableConfigs.GetScriptableObjectData(treeViewState.selectedIDs[0]);
            ScriptableObjectDataInspector.Instance.OnInspectorGUI(data, this, currrentScriptableConfigs); 
        }
        public string GetDisplayName(ScriptableObjectConfigs config)
        {
            if (string.IsNullOrEmpty(config.displayName))
                return config.name;

            return string.Format("{0}({1})", config.name, config.displayName);
        }
         
        internal void SetCurrentConfigs(ScriptableObjectConfigs current) {

            currentID = -1; // 重置当前选中的id
            currrentScriptableConfigs = current;
            GUI.FocusControl(null);
            if (scriptableObjectListTree != null)
            {
                scriptableObjectListTree.Reload();
            }

            SelectGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath(current)); 
        }

        public static List<Type> GetAllScriptableObjectDataTypes()
        {
            List<Type> states = new List<Type>();

            states.Add(typeof(ScriptableObjectData));

            string[] scripts = AssetDatabase.FindAssets("t:Script");

            foreach (var item in scripts)
            {
                string path = AssetDatabase.GUIDToAssetPath(item);
                MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>(path);

                if (script == null) continue;

                Type type = script.GetClass();

                if (type == null) continue;

                if (type.IsSubclassOf(typeof(ScriptableObjectData)))
                    states.Add(type);
            }

            return states;
        }

        public void SetSelection(int id) 
        {
            if (scriptableObjectListTree != null)
                scriptableObjectListTree.SetSelection(new int[] { id });
            else 
            {
                EditorApplication.delayCall += () => 
                {
                    if (scriptableObjectListTree != null)
                        scriptableObjectListTree.SetSelection(new int[] { id });
                };
            }
        }


        internal ScriptableObjectConfigs GetCurrentConfig()
        {
            if (!string.IsNullOrEmpty(SelectGUID))
            {
                string assets_path = AssetDatabase.GUIDToAssetPath(SelectGUID);
                ScriptableObjectConfigs config = AssetDatabase.LoadAssetAtPath<ScriptableObjectConfigs>(assets_path);

                if (config != null)
                    return config;
            }

            List<ScriptableObjectConfigs> configs = ScriptableObjectConfigsController.GetAllConfigs();

            if (configs == null || configs.Count == 0)
                return null;

            SelectGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(configs[0]));
            return configs[0];
        }



#endregion


        #region 创建

        private void CreateNew()
        {
            string path = EditorUtility.OpenFolderPanel("请选择文件夹", Application.dataPath, string.Empty);

            if (string.IsNullOrEmpty(path)) return;

            if (path.StartsWith(Application.dataPath))
            {
                path = path.Replace(Application.dataPath, string.Empty);
                path = string.Format("Assets{0}", path);
                ScriptableObjectConfigs skillsConfig = CreateInstance<ScriptableObjectConfigs>();
                ScriptableObjectConfigsController.CreateAsset(skillsConfig, path);

                SelectGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(skillsConfig));
                EditorGUIUtility.PingObject(skillsConfig);

                if (scriptableObjectListTree != null)
                    scriptableObjectListTree.Reload(); 
            }
            else
            {
                this.ShowNotification(new GUIContent("请把资源保存到Assets目录下!"));
            }
        }
         
        #endregion


    }

}

